AWS IoT Coreポリシーでiot:Publishとiot:Receiveをまとめて許可すると、トピック設計によっては本来必要なアクションまでブロックするかもしれない

AWS IoT Coreポリシーでiot:Publishとiot:Receiveをまとめて許可すると、トピック設計によっては本来必要なアクションまでブロックするかもしれない

パブリッシュ用トピックとサブスクライブ用トピックを分けている場合、AWS IoT Coreポリシーで「同じ"topic/"で始まるから」と、iot:Publishとiot:Receiveをまとめて許可すると、本来必要なアクションまでブロックするおそれがあります。
Clock Icon2024.09.17

IoT デバイスでメッセージを受信できない

おのやんです。

みなさん、AWS IoT Core(以下、IoT Core)にて、デバイス上でメッセージの受信ができない現象に遭遇したことはありませんか?私はあります。

具体的には以下の現象です。

  • IoT CoreにはIoT Core ポリシーを設定している
  • デバイスからIoT Coreへのメッセージのパブリッシュは可能
  • IoT Coreからデバイスへメッセージを送信しても、デバイス側でメッセージを認識しない

こちらの現象について調査する機会がありましたので、これから紹介していきます。

3行まとめ

  • パブリッシュ用トピックとサブスクライブ用トピックを分けている場合、IoT Coreポリシーをまとめて許可すると本来必要なアクションまでブロックする可能性がある
  • iot:Receiveアクションを許可する対象は、サブスクライブ用トピック
  • 許可するアクションは、ひとつひとつ分けて書こう

IoT Core ポリシーがどうなっていたか

今回のケースでは、IoT Coreで以下のようにポリシーを設定していました。公式ドキュメントにも載っている、デバイスの接続・メッセージのやりとりをIoT Coreに登録しているデバイスのみに限定しているポリシーです。

https://docs.aws.amazon.com/iot/latest/developerguide/pub-sub-policy.html

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:ap-northeast-1:<account_id>:client/${iot:Connection.Thing.ThingName}",
      "Condition": {
        "Bool": {
          "iot:Connection.Thing.IsAttached": [
            "true"
          ]
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Receive"
      ],
      "Resource": "arn:aws:iot:ap-northeast-1:<account_id>:topic/pub/${iot:Connection.Thing.ThingName}"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": "arn:aws:iot:ap-northeast-1:<account_id>:topicfilter/sub/${iot:Connection.Thing.ThingName}"
    }
  ]
}

また今回は、IoT Coreトピックの設計として、パブリッシュ用とサブスクライブ用でそれぞれトピックをpub/始まりとsub/始まりに分けていました。

原因

では、上記の設定でデバイスのメッセージ受信が許可されない原因はどこにあるのでしょうか?

こちらに結構時間を溶かしてしまったのですが、原因はこの部分です。
topic/で指定できるiot:Publishiot:Receiveを同じResourceで許可しています。

    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Receive"
      ],
      "Resource": "arn:aws:iot:ap-northeast-1:<account_id>:topic/pub/${iot:Connection.Thing.ThingName}"
    },

こちらお気づきの方もいるかと思いますが、この状態ではiot:Publishiot:Receiveもパブリッシュ用トピックを許可してしまっています

本来であれば、iot:Receiveを許可する対象は、パブリッシュ用ではなくサブスクライブ用のトピックです

「トピックを同じtopic/で指定できるから、iot:Publishiot:Receiveをまとめて許可しよう」と考えたことが原因で、本体sub/始まりのトピックを指定するべきiot:Receiveアクションにて、pub/始まりのトピックを指定していました。

そのため、横着せずににポリシーをiot:Publishiot:Receiveをしっかり書き分けて、めでたくデバイス上でメッセージを受信できるようになりました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Condition": {
        "Bool": {
          "iot:Connection.Thing.IsAttached": [
            "true"
          ]
        }
      },
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:ap-northeast-1:<account_id>:client/${iot:Connection.Thing.ThingName}"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": "arn:aws:iot:ap-northeast-1:<account_id>:topic/pub/${iot:Connection.Thing.ThingName}"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Receive",
      "Resource": "arn:aws:iot:ap-northeast-1:<account_id>:topic/sub/${iot:Connection.Thing.ThingName}"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": "arn:aws:iot:ap-northeast-1:<account_id>:topicfilter/sub/${iot:Connection.Thing.ThingName}"
    }
  ]
}

ポリシーJSONの記述では横着しない

ものすごく細かいミスですが、どのリソースを許可するかという最も基本的な考えを改めて確認する必要があるなと思いました。特にIoT Coreポリシーではデバイスとのやりとりに関しての権限となるので、詳細に記述することが大切です。

余談ですが、公式ドキュメントではiot:Publishiot:Receiveはしっかり書き分けされていたので、ちゃんと公式ドキュメントを読みましょうという自戒も込めてみました。では!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.